"struct" wird auf einem ESP8266 anders behandelt wie auf einem Arduino
|
22.10.2017, 21:48
(Dieser Beitrag wurde zuletzt bearbeitet: 23.10.2017 00:38 von ardu_arne.)
Beitrag #1
|
|||
|
|||
"struct" wird auf einem ESP8266 anders behandelt wie auf einem Arduino
Hallo,
ich habe auf einem ESP8266 und einem Arduino MEGA2560 folgendes angelegt: Code: struct Code: template <typename T> unsigned int serialPrintAnything (const T& value) der ESP8266 liefert: Code: Size: 12 Byte - Data = 0x01 0x00 0x00 0x00 0x55 0x44 0x33 0x22 0x88 0x77 0x00 0x00 Code: Size: 7 Byte - Data = 0x01 0x55 0x44 0x33 0x22 0x88 0x77 Solange man mit den Daten auf einem System bleibt ist das kein Problem. Aber wenn man die Daten seriell (I2C, SPI, UDP, ect.) am Stück zum jeweils anderen System überträgt passen die nicht mehr in die dort angelegte struct(ur). Hat jemand eine Idee wie man das Problem (einfach) lösen könnte? Gruß Arne Gruß Arne Mit zunehmender Anzahl qualifizierter Informationen bei einer Fragestellung, erhöht sich zwangsläufig die Gefahr auf eine zielführende Antwort. |
|||
23.10.2017, 09:15
(Dieser Beitrag wurde zuletzt bearbeitet: 23.10.2017 09:43 von MicroBahner.)
Beitrag #2
|
|||
|
|||
RE: "struct" wird auf einem ESP8266 anders behandelt wie auf einem Arduino
Hallo Arne,
(22.10.2017 21:48)ardu_arne schrieb: Beim ESP wird also scheinbar immer auf die Länge des größten Elementes mit "0" aufgefüllt.nicht generell, und eigentlich wird auch nicht aufgefüllt, sondern es entstehen Lücken durch das Alignment des Compilers auf Speichergrenzen. Das ist ein 'Problem' aller 32-Bit Rechner. Wenn Du eine 32-Bit-Variable definierst, muss die auch auf einer 32-Bit-Grenze liegen. Hast Du vorher kürzere Variablen definiert, entstehen gegebenfalls Lücken, damit die 32-Bit Variable wieder richtig an der Speichergrenze ausgerichtet ist. Du hättest am Anfang des Structs bis zu 4 byte-Variable definieren können, ohne dass da was zusätzlich 'aufgefüllt' worden wäre. z.B. bei dieser Struktur: Code: struct Auch so: Code: struct Datenaustausch zwischen 32-Bit und 8-Bit Rechnern hat also durchaus seine Tücken, wobei man gegebenenfalls auch noch zwischen 'little endian' and 'big endian' unterscheiden muss ![]() Edit: Auch bei 16-Bit Variablen ist zu beachten, dass die auf einer geraden Adresse liegen müssen, sonst entstehen ebenfalls Lücken durch das Alignment des Compilers. Also so: Code: struct Gruß, Franz-Peter |
|||
23.10.2017, 11:00
Beitrag #3
|
|||
|
|||
RE: "struct" wird auf einem ESP8266 anders behandelt wie auf einem Arduino
Hallo Franz-Peter,
herzlichen Dank für die Erläuterungen. Ich habe es jetzt so verstanden dass man das eigentliche Problem nicht beheben kann weil es ein zum jeweiligen Prozessortyp gehörendes "Naturgesetz" ist. Einzig die negativen Auswirkungen kann man beseitigen wenn man die Struktur so anlegt dass die (kleinen) Variablen immer auf einer zum Prozessortyp passenden 8, 16, 32 oder 64-Bit-Grenze liegen. Um das zu erreichen füllt man die Struktur an den betroffenen Stellen mit entsprechenden Nutz- oder Dummybytes auf. Durch passende Umsortierung der Nutzbytes kann man also Platz sparen weil man weniger Dummybytes braucht. Jetzt kann man nur noch froh sein dass in diesen Fall beide Prozessoren mit Big-Endian arbeiten. Sonst wäre das Chaos komplett. Gruß Arne Gruß Arne Mit zunehmender Anzahl qualifizierter Informationen bei einer Fragestellung, erhöht sich zwangsläufig die Gefahr auf eine zielführende Antwort. |
|||
23.10.2017, 11:03
(Dieser Beitrag wurde zuletzt bearbeitet: 23.10.2017 11:03 von MicroBahner.)
Beitrag #4
|
|||
|
|||
RE: "struct" wird auf einem ESP8266 anders behandelt wie auf einem Arduino
Genau so ist es
![]() Gruß, Franz-Peter |
|||
23.10.2017, 11:18
(Dieser Beitrag wurde zuletzt bearbeitet: 23.10.2017 11:30 von Tommy56.)
Beitrag #5
|
|||
|
|||
RE: "struct" wird auf einem ESP8266 anders behandelt wie auf einem Arduino
Man kann das Problem aber auch ohne Füllbytes lösen, indem man dem Compiler sagt, dass er das alles packen soll.
align.ino: Code: #include "align.h" Code: template <typename T> unsigned int serialPrintAnything (const T& value) Code: Start Das sollte aber nur für derartige Übergabestrukturen angewandt werden, da der Zugriff für 32-Bit-Prozessoren auf die Variablen, die nicht auf 32-Bit-Grenzen liegen, langsamer ist. Gruß Tommy Edit: Das __attribute__ ist nicht ANSI-konform. Edit2: Es gibt noch eine andere Schreibweise, die ebenfals auf beiden Architekturen die gleiche Ausgabe erzielt. Der Wert in Klammkern gibt die Anzahl Bytes an, auf die gepackt wird. Hier also 1 Byte: Code: #pragma pack(1) "Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt) |
|||
23.10.2017, 11:44
Beitrag #6
|
|||
|
|||
RE: "struct" wird auf einem ESP8266 anders behandelt wie auf einem Arduino
Hallo Tommy,
ja, da war doch noch was... das pack() ist mir nicht eingefallen ![]() aber, wie Du schon sagst, ist das für einen 32-bitter recht ungünstig. Wenn möglich würde ich die Variante mit der optimalen Variablenanordnung vorziehen. Gruß, Franz-Peter |
|||
23.10.2017, 12:07
Beitrag #7
|
|||
|
|||
RE: "struct" wird auf einem ESP8266 anders behandelt wie auf einem Arduino
Mit den Vorschlägen von Tommy eröffnen sich ja ganz neue Möglichkeiten.
![]() Aber mir wird es damit dann doch zu komplex und undurchsichtig. ![]() Ich bleibe dann doch lieber dabei die Struktur händisch so zu sortieren dass möglichst wenige "Füllbytes" nötig sind. Damit kann ich dann auch mögliche Inkompatibilitäten mit künftigen Compiler Versionen ausschließen die dann evtl. das Packen anders behandeln als derzeit aktuelle Compiler Versionen. Gruß Arne Gruß Arne Mit zunehmender Anzahl qualifizierter Informationen bei einer Fragestellung, erhöht sich zwangsläufig die Gefahr auf eine zielführende Antwort. |
|||
|
|
Benutzer, die gerade dieses Thema anschauen: 1 Gast/Gäste