Hey hallo,
Ich benötige auf meinem Controller eine struktur. Diese strutkur wird in
der MAIN Ständig abgepollt und es geben eben Ereignisse die getriggert
werden, sobald sich an der Struktur was ändert. Über I2C soll aber
zugriff auf diese Struktur möglich sein. Ich hatte jetzt gedacht ich
caste die struct einfach mal zu einem char* aber irgendwie scheint im
speicher einige anders zu sein. Wie serialisiert man eine strukt
möglichst einfach?
attiny417 schrieb:> aber irgendwie scheint im> speicher einige anders zu sein.
Auf einem Attiny417? Welcher Compiler, welche Version, welche
Optimierung?
Oliver
>>Auf einem Attiny417? Welcher Compiler, welche Version, welche>>Optimierung?
zunächste Probiere ich mit microchip studio. Später (in serien
Produktion) wolte ich avr-gcc + avr dude nehmen.
attiny417 schrieb:> zunächste Probiere ich mit microchip studio. Später (in serien> Produktion) wolte ich avr-gcc + avr dude nehmen.
Aha...
Aber wenn du schon das Studio benutzt, schau halt mal in der Simulation
in den Speicher, was da so steht..
Der avr-gcc 11, den ich hier habe, legt das alles so an, wie das da
steht. Das Studio verwendet eine ältere Version. Vielleicht fehlt dem da
ein packed, auch wenn das auf einem AVR eigentlich nicht beötigt werden
sollte.
Oliver
attiny417 schrieb:> Ich hatte jetzt gedacht ich> caste die struct einfach mal zu einem char* aber irgendwie scheint im> speicher einige anders zu sein.
Was passiert denn? Mit welchem Code?
Deine Struktur hat ja mindestens 224 Byte (wenn ich richtig gezählt
hab), je nach Allignment auch an die 256. Soll das so?
Typische Probleme sind
a) Allignment (REGISTER.Unddas fängt bei [4] an und nicht bei [2])
b) Endianess (REGISTER.dies=3 schreibt 0,3 in den Speicher oder 3,0)
c) Bitfelder sind ein eigenes Fass
d) Dein Debugger ("im Speicher anders") ist wieder ein eigenes Fass
e) Warnungen aus (und Schreibfehler, Verständnisfehler)
f) ...
>> a) Allignment (REGISTER.Unddas fängt bei [4] an und nicht bei [2])>> b) Endianess (REGISTER.dies=3 schreibt 0,3 in den Speicher oder 3,0)>> c) Bitfelder sind ein eigenes Fass>> d) Dein Debugger ("im Speicher anders") ist wieder ein eigenes Fass>> e) Warnungen aus (und Schreibfehler, Verständnisfehler)>> f) ...
I know :D
A) Im Beispiel oben wird man Problme mit dem Alignment bekommen, in
meiner struct passe ich drauf auf das jede struct ein vielfaches von 4
byte hat.
B) Endianess -> naja beide compiler die ich nutzen werde sind vom grunde
auf gcc compiler, ich denke da springt das alignment nicht.
C) Siehe A / bzw Bitfelder nutze ich seit jahren.
d/e) -> feolgefehler durch fehlinterpretation :D
attiny417 schrieb:> I know :D
Machst Du Witze? Du schreibst, Du hast ein Problem
> aber irgendwie scheint im speicher einige anders zu sein.
schreibst nicht dazu welches, sondern erklärst stattdessen, dass Du
keine Fehler machst.
Dass der Compiler die Endianess bestimmt ist sicher nur ein Versehen.
Und die genaue Größe der Struktur ist relativ egal, sizeof & co
berücksichtigen das.
>>Dass der Compiler die Endianess bestimmt ist sicher nur ein Versehen.
Es ist leider nicht festgelegt, es kann es sein das ein anderer Compiler
die Daten anders herum Speichert.
>>Und die genaue Größe der Struktur ist relativ egal, sizeof & co>>berücksichtigen das.
Das stimmt nicht.
[code]
typedef struct {
ui8 blub;
}test1;
typedef struct {
ui8 blub;
ui8 blub2;
}test2;
[/code}
soizeof(test2) wird 2 oder 4 ausgeben, genauso wie soizeof(test1). Es
sei denn man "packt" mit #pragma push/pop
Daher ist es sehr sinnvoll darauf zu achten das man die size immer bei
einem vielfachen von 4 hält, wenn man strukturen serialisieren möchte.
attiny417 schrieb:> es kann es sein das ein anderer Compiler> die Daten anders herum Speichert.
natürlich. Nur kommt der Compiler in Teufels-Küche, wenn er sich da
nicht am µC und seinen Fähigkeiten orientiert. Und z.B. bei Deinem
Nick-uC hätte ich jetzt nicht erwartet, dass er da flexibel ist.
attiny417 schrieb:> Daher ist es sehr sinnvoll darauf zu achten das man die size immer bei> einem vielfachen von 4 hält, wenn man strukturen serialisieren möchte.
Kann man so sehen. Man kann es auch anders rum sehen, dass nämlich der
Compiler schon dafür sorgt, dass nichts schief geht. Er "macht" Deine
Strukturen so groß, dass es passt. Probleme gibt es nur, wenn Du
irgendwelche Dinge selbst ausrechnest (ohne sizeof oder []), vor allem
wenn es um Arrays von Strukturen geht.
Aber wenn bei Dir doch alles funktioniert, dann OK, freut mich!
Für Telegramm, die seriell übertragen werden, dürfen keine Lücken in der
Struktur vorhanden sein.
Abhilfe:
1
structmy_struct{
2
chara;
3
intb;
4
}__attribute__((packed));
Bei unterschiedlichen Prozessorfamilien kann die Reihenfolge von Low und
High vertauscht sein. Diese müssen dann im Empfänger gedreht werden.
char* speichert in der Struktur nur einen Zeiger vom Typ char !
attiny417 schrieb:> B) Endianess -> naja beide compiler die ich nutzen werde sind vom grunde> auf gcc compiler, ich denke da springt das alignment nicht.
Das hat mehr mit der Zielplattform als mit dem Compiler zu tun. Daher
kommt es stark darauf an, wer über I²C zugreifen will:
attiny417 schrieb:> Über I2C soll aber zugriff auf diese Struktur möglich sein.
Wenn das auch ein AVR mit gcc ist, brauchst du dir keine Sorgen machen.
Ansonsten musst du da genauer aufpassen.
Gerald K. schrieb:> Für Telegramm, die seriell übertragen werden, dürfen keine Lücken in der> Struktur vorhanden sein.
Die dürfen schon vorhanden sein. Sie müssen nur beidseitig gleich sein
(und zwar unabhängig davon, wie sie übertragen werden). Das kann man
z.B. auch erreichen, indem man zum Alignment Dummy-Elemente einfügt. Und
man sollte ausschließlich die uint*_t-Datentypen oder vergleichbare mit
genau definierter Breite nutzen.
> Abhilfe:> struct my_struct {> char a;> int b;> } _attribute_ ((packed));
Das kann fehlschlagen, wenn der Prozessor bestimmte Alignments zwingend
voraussetzt. Und int kann auch auf Sender- und Empfänger-Seite
unterschiedlich groß sein.
> Bei unterschiedlichen Prozessorfamilien kann die Reihenfolge von Low und> High vertauscht sein. Diese müssen dann im Empfänger gedreht werden.
Oder im Sender. Man muss sich halt auf eine gemeinsame Byteoder einigen
oder diese beim Start aushandeln.
Rolf M. schrieb:> Gerald K. schrieb:>> Für Telegramm, die seriell übertragen werden, dürfen keine Lücken in der>> Struktur vorhanden sein.>> Die dürfen schon vorhanden sein. Sie müssen nur beidseitig gleich sein> (und zwar unabhängig davon, wie sie übertragen werden).
Genau.
Ein Problem ergibt sich vielleicht, wenn man solche Strukturen
vergleicht, z.B. mit memcmp.
A. S. schrieb:> Rolf M. schrieb:>> Gerald K. schrieb:>>> Für Telegramm, die seriell übertragen werden, dürfen keine Lücken in der>>> Struktur vorhanden sein.>>>> Die dürfen schon vorhanden sein. Sie müssen nur beidseitig gleich sein>> (und zwar unabhängig davon, wie sie übertragen werden).>> Genau.>> Ein Problem ergibt sich vielleicht, wenn man solche Strukturen> vergleicht, z.B. mit memcmp.
Das hat aber nichts mit der Übertragung zu tun.
mh schrieb:> Das hat aber nichts mit der Übertragung zu tun.
natürlich nicht. Darum schrieb ich ja:
A. S. schrieb:> die genaue Größe der Struktur ist relativ egal,
mir ging es nur um Geralds Aussage, vielleicht hat er das verwechselt.