Moin,
ich wühle mich jetzt schon seit stunden durch die Suchfunktion und das
Tutorial, werde aber leider nicht fündig, deshalb versuche ich es jetzt
so:
Randbedingungen: AVR Studio, ATMega 128, GCC.
Ich habe mehrer (momentan 5) Structs unterschiedlicher größe, die
jeweils einen Datensatz an Einstellungen für meine Steuerung enthalten.
Ich will nun jeweils 16 Speicher haben, wo ich also den aktuellen struct
auf eine definierte Position ablege.
Am ende will ich also auf '4' klicken und er schreibt mir den Datensatz
nummer 4 in den aktuellen Wertesatz. (ist klar, was ich mein, oder?)
Ich versuche jetzt wie folgt ein array anzulegen, wo die
speicherpositionen liegen:
Dabei beträgt der Datensatz dieses Structs 6 byte, es soll also alle 6
byte ein neuer speicherpunkt liegen.
zum speichern nutze ich, nachdem ich die aktuellen Werte in die
work-variable kopiert habe:
Das Problem ist jetzt, dass der erste Wert noch ordendlich gespeichert
wird. Beim zweiten Resettet er. (bei der überprüfung des Adresswertes
kommt auch nicht der heraus, der im Array steht und m.e. verwendet
werden sollte..)
Ich nehme mal an, dass es sich um ein fundamentales Problem handelt.
Schonmal vielen Dank für Tips und Antworten.
Käase schrieb:
> Am ende will ich also auf '4' klicken und er schreibt mir den Datensatz> nummer 4 in den aktuellen Wertesatz. (ist klar, was ich mein, oder?)
Nein
> Dabei beträgt der Datensatz dieses Structs 6 byte, es soll also alle 6> byte ein neuer speicherpunkt liegen.
?????
Die Datensätze für die Parameter werden doch immer gleich groß sein, es
ändert sich ja nur der Inhalt, oder?
Warum verschieden große Datensätze?
Du braucht ein struct für die Parameter die Du speichern willst, und
dann legst Du dir ein Array aus 16 Elementen mit dieser Struct an.
Dann kannst Du auf das 1. Element zugreifen oder auf 4., usw. (lesend
oder schreibend).
Hallo Klaus,
mh, also das Problem ist, dass ich 5 structs habe, die ich speichern
will und die verschieden groß sind.
Also
struct a = 6 byte
struct b = 6 byte
struct c = 22 byte
struct d = 22 byte
struct e = 103 byte
und davon sollen jeweils 16 Datensätze im eeprom sein.
für diese Datensätze gibt es immer einen aktuellen, der vom Programm
verwendet wird.
Jetzt habe ich eine Eingabemaske, mit der ich die Funktion aufrufe
"speicher_struct_a(wert)" oder "lade_struct_b(wert)".
Ich will nun also auf den entsprechenden block zugreifen.
(das klärt vielleicht die Frage
>> Dabei beträgt der Datensatz dieses Structs 6 byte, es soll also alle 6>> byte ein neuer speicherpunkt liegen.>?????
oben hab ich ja die Tabelle angehängt mit den entsprechenden größen. Die
Vorstellung dieses Arrays war, entsprechend alle 6 Byte (für den struct
a) eine Adresse zu benennen, auf die ich zugreifen kann. Für die anderen
Datensätze sähe das dann entsprechend im 22byte oder 103 byte - Raster
aus.
Käase schrieb:
> mh, also das Problem ist, dass ich 5 structs habe, die ich speichern> will und die verschieden groß sind.>> Also> struct a = 6 byte> struct b = 6 byte> struct c = 22 byte> struct d = 22 byte> struct e = 103 byte>> und davon sollen jeweils 16 Datensätze im eeprom sein.
Dann legst du eben im EEPROM von jeder struct ein Array der Größe 16 an.
Ich sehe momentan nicht, was das Problem sein soll.
Ich verstehe auch noch nicht, warum du im Augenblick im EEPROM
uint16_t-Arrays anlegst, wo du doch eigentlich structs speichern willst.
Klaus Falser schrieb:
> Du braucht ein struct für die Parameter die Du speichern willst, und> dann legst Du dir ein Array aus 16 Elementen mit dieser Struct an.> Dann kannst Du auf das 1. Element zugreifen oder auf 4., usw. (lesend> oder schreibend).
Beim AVR kann man nicht einfach über eine Struct oder ein Array von
Structs auf Inhalte des EEPROM zugreifen - weder lesend noch schreibend.
@Käase
Allerdings kannst Du Dir durch das Deklarieren entsprechender Structs
und Arrays, die das Layout Deiner Daten im EEPROM wiederspiegeln das
händische Ausrechnen und Eintippen der Offsets ersparen, was Fehlern
vorbäugt und sich spätestens dann auszahlt, wenn Du mal einen Deiner
Structs in der Größe verändern mußt.
Aber zu Deinem eigentlichen Problem: Könnte es sein, daß Deine
Versorgungsspannung nicht gut genug gepuffert ist und durch die
Stromspitze beim Schreiben ins EEPROM zusammenbricht, was dann zu dem
Reset führt?
Stefan Ernst schrieb:
> Ich verstehe auch noch nicht, warum du im Augenblick im EEPROM> uint16_t-Arrays anlegst, wo du doch eigentlich structs speichern willst.
In dem uint16_t-Array stehen die Offsets, die die einzelnen Instanzen
der Structs im EEPROM haben sollen.
>Aber zu Deinem eigentlichen Problem: Könnte es sein, daß Deine>Versorgungsspannung nicht gut genug gepuffert ist und durch die>Stromspitze beim Schreiben ins EEPROM zusammenbricht, was dann zu dem>Reset führt?
Ich glabue das kann ich ausschließen. Das Problem war eher, dass ein
völlig irrer wert auftauchte, der als adresse im EEprom herhalten
sollte.
.. also vielleicht klärt sich mein Problem wenn ich kurz beschreibe
warum ich diese arrays haben will: die sollen mir die Adresse der
Datenwerte im EEProm geben. Eigentlich brauche ich die wirklich nicht im
EEprom abzulegen, wie wäre denn die schönste methode das zu lösen?? [ich
habe mich jetzt versucht an das Tutorial zu halten].
@Reinhard Max:
>Allerdings kannst Du Dir durch das Deklarieren entsprechender Structs>und Arrays, die das Layout Deiner Daten im EEPROM wiederspiegeln das>händische Ausrechnen und Eintippen der Offsets ersparen, was Fehlern>vorbäugt und sich spätestens dann auszahlt, wenn Du mal einen Deiner>Structs in der Größe verändern mußt.
wie genau funktioniert das? soetwas in der art suche ich, aber eben mit
der möglichkeit, diese Adressen auch wiederzufinden..
Achso,
und so wie ich es oben beschreibe werden einfach nicht die Adressen
übernommen! Wenn das klappen würde, wäre ich fürs erste zufrieden (auch
wenn es unschön ist), aber es klappt nicht!
(vielleicht weiß da noch jemand bescheid, warum das so ist.. oder wie
man das hinbekommt)
Ok, also:
1)
Bei den Codezeilen im ersten Post fehlt jeweils ein eeprom_read_word für
das Lesen der Offsets aus dem EEPROM, daher der Datenmüll.
2)
Das Array mit den Offsets (was ja auch im EEPROM liegt) kollidiert mit
deiner eigenen Adressvergabe. Entweder du verwaltest die Lage aller
Daten im EEPROM selber, oder du überlässt das dem Compiler. "Gemischter
Betrieb" ist keine so gute Idee.
3)
Warum so kompliziert?
Käase schrieb:
> wie genau funktioniert das? soetwas in der art suche ich, aber eben mit> der möglichkeit, diese Adressen auch wiederzufinden..
Hier mal ein Beispiel:
Die Structs foo und bar stehen für Deine vorhandenen Structs. Die werden
in foobar zu einem abzuspeichernden Datensatz zusammengefaßt. Davon
sizeof() sagt Dir wie groß ein Datensatz ist. Diese Größe multipliziert
mit der Nummer des Datensatzes gibt seinen Offset. Wenn Du nur eine
Struct aus einem Datensatz lesen willst, kommt noch offsetof() dazu
(stddef.h). Beispielsweise findest Du die Struct bar des dritten
Datensatzes an der Adresse 2*sizeof(struct foobar)+offsetof(struct
foobar, baar) .
Hallo Stefan, ich glaube mir wird gerade etwas klar!
Ich habe die Speicherverwaltung die ganze Zeit total falsch verstanden!!
irgendwie ist mir da einiges durch die Lappen gegangen, ich dachte die
Adressen würde ich direkt verwalten.
Kurzum: ich habe es gerade gegengecheckt mit mehreren Structs und es
läuft!
Vielen Dank allen, die geholfen haben und sich Gedanken gemacht haben!!
@Reinhard
ich lese gerade noch deine Anmerkungen.
So ginge es sicher auch, aber ist wohl komplizierter als ich es
benötige.
Trotzdem Danke für die Erläuterungen!
Vielleicht noch eine Verständnisfrage: wo befindet sich der Zeiger auf
die Struct - Offsets, wenn die structs doch ins EEprom gelegt sind..
also ich hatte ja die ganze Zeit gedacht, ich bräuchte da noch einen
Wert / Adresse im Ram des µCs, die ich verwende. Oder braucht es eben
genau das überhaupt nicht udn der µC liest direkt den eeprom aus um die
Adresse zu finden?
Käase schrieb:
> @Reinhard>> ich lese gerade noch deine Anmerkungen.>> So ginge es sicher auch, aber ist wohl komplizierter als ich es> benötige.
Soweit ich es verstehe, macht meine Variante im Endeffekt genau das
gleiche wie die von Stefan, nur daß ich es in ANSI-C gelöst habe, weil
mir die EEMEM-Erweiterung von avr-gcc bisher nicht geläufig war.
Stefans Lösung ist etwas komfortabler zu benutzen, meine ließe sich
vermutlich leichter anpassen, falls der Platz im internen EEPROM nicht
mehr ausreicht und die Daten deshalb in ein externens EEPROM sollen, das
per I²C oder SPI angebunden ist.
Mit einem Makro läßt sich meine Variante auch noch soweit vereinfachen,
daß Du am Ende nur noch sowas in der Art schreiben mußt:
um die Struct a des i-ten Datensatzes aus dem EEPROM zu lesen.
> Vielleicht noch eine Verständnisfrage: wo befindet sich der Zeiger auf> die Struct - Offsets, wenn die structs doch ins EEprom gelegt sind.
Das sind eigentlich keine Zeiger im C-Sinn, sondern schlicht die
EEPROM-Adressen, wie Du sie in Deinem ersten Beispiel explizit
aufgelistet hattest. Übrigens müßte das auch funktionieren, wenn Du von
eeFooByteArray1 die EEMEM-Deklaration entfernst. Das Problem war, daß Du
das Array im EEPROM deklarierst, dann aber so verwendest, als würde es
im RAM liegen, wo Du es in diesem Fall ja auch brauchst.
> Oder braucht es eben genau das überhaupt nicht udn der µC liest> direkt den eeprom aus um die Adresse zu finden?
Die Adresse wird schon im RAM (bzw. einem Register) aus der Größe der
Struct und den Array-Index berechnet, aber sie muß eben ihrerseits nicht
im EEPROM abgelegt werden, weil das Programm ja die Struktur der Daten
im EEPROM kennt.
Reinhard Max schrieb:
> Soweit ich es verstehe, macht meine Variante im Endeffekt genau das> gleiche wie die von Stefan, nur daß ich es in ANSI-C gelöst habe, weil> mir die EEMEM-Erweiterung von avr-gcc bisher nicht geläufig war.
Das EEMEM ist keine spezielle EEPROM-Erweiterung. Es ist nur ein Makro,
dass an die Variable ein Section-Attribut "dranpappt", damit die
Adressvergabe für diese Variablen gesondert gehandhabt werden kann.
Exakt den gleichen Mechanismus kann man auch verwenden, um Variablen in
eine NoInit-Section zu legen, oder in externes Ram.