INFO: Dieses Forum nutzt Cookies...
Cookies sind für den Betrieb des Forums unverzichtbar. Mit der Nutzung des Forums erklärst Du dich damit einverstanden, dass wir Cookies verwenden.

Es wird in jedem Fall ein Cookie gesetzt um diesen Hinweis nicht mehr zu erhalten. Desweiteren setzen wir Google Adsense und Google Analytics ein.

Antwort schreiben 
 
Themabewertung:
  • 0 Bewertungen - 0 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
"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
{
  byte     val1 = 0x01;
  uint32_t val2 = 0x22334455;
  uint16_t  crc = 0x7788;
} testStruct;
mit:
Code:
template <typename T> unsigned int serialPrintAnything (const T& value)
{
  const byte * p = (const byte*) &value;
  unsigned int i;
  Serial.print("Size: "); Serial.print(sizeof value); Serial.print(" Byte - Data = ");
  for (i = 0; i < sizeof value; i++) {
    Serial.print("0x");
    if (*p <= 15) Serial.print("0");
    Serial.print(*p++, HEX);
    Serial.print(" ");
  }
  Serial.println();
  return i;
}
gebe ich den Inhalt von "testStruct" seriell aus.

der ESP8266 liefert:
Code:
Size: 12 Byte - Data = 0x01 0x00 0x00 0x00 0x55 0x44 0x33 0x22 0x88 0x77 0x00 0x00
der MEGA2560 liefert:
Code:
Size: 7 Byte - Data = 0x01 0x55 0x44 0x33 0x22 0x88 0x77
Beim ESP wird also scheinbar immer auf die Länge des größten Elementes mit "0" aufgefüllt.

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.
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
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
{
  byte     val1 = 0x01;
  byte     val12 = 0x02;
  byte     val13 = 0x03;
  byte     val14 = 0x04;
  uint32_t val2 = 0x22334455;
  uint16_t  crc = 0x7788;
  uint16_t  crc1 = 0x99aa;
} testStruct;
gibt es gar keine Auffüllungen mit '0', da alles genau in die 32-Bit Speicherorganisation hineinpasst.
Auch so:
Code:
struct
{
  byte     val1 = 0x01;
  byte     val12 = 0x02;
  uint16_t  crc = 0x7788;
  uint32_t val2 = 0x22334455;
} testStruct;
geht es ohne Lücken und ist dann bei ESP und Mega identisch.
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 Wink

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
{
  byte     val1 = 0x01;
  uint16_t  crc = 0x7788;
  byte     val12 = 0x02;
  uint32_t val2 = 0x22334455;
} testStruct;
funktioniert es nicht!

Gruß, Franz-Peter
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
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.
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
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 Smile

Gruß, Franz-Peter
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
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"

struct testStruct{
  byte     val1 = 0x01;
  uint32_t val2 = 0x22334455;
  uint16_t  crc = 0x7788;
}__attribute__ ((packed)) myTest;

void setup() {
  Serial.begin(115200);
  Serial.println("\nStart");
  serialPrintAnything(myTest);
}

void loop() {
}
Align.h (enthält die unveränderte Ausgabefunktion)
Code:
template <typename T> unsigned int serialPrintAnything (const T& value)
{
  const byte * p = (const byte*) &value;
  unsigned int i;
  Serial.print("Size: "); Serial.print(sizeof value); Serial.print(" Byte - Data = ");
  for (i = 0; i < sizeof value; i++) {
    Serial.print("0x");
    if (*p <= 15) Serial.print("0");
    Serial.print(*p++, HEX);
    Serial.print(" ");
  }
  Serial.println();
  return i;
}
Beide Prozessoren ergeben die gleiche Ausgabe:
Code:
Start
Size: 7 Byte - Data = 0x01 0x55 0x44 0x33 0x22 0x88 0x77
Auf diese Weise kann man Strukturen für den Datenaustausch zwischen den beiden Welten definieren.
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)
struct testStruct{
  byte     val1 = 0x01;
  uint32_t val2 = 0x22334455;
  uint16_t  crc = 0x7788;
} myTest;

"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
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 Sad

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
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
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.Exclamation Danke dafür!
Aber mir wird es damit dann doch zu komplex und undurchsichtig. Undecided

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.
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
Antwort schreiben 


Möglicherweise verwandte Themen...
Thema: Verfasser Antworten: Ansichten: Letzter Beitrag
  ESP8266-12E & Pullup I2C rev.antun 19 548 Heute 06:19
Letzter Beitrag: N1d45
  Abgespeckter Sketch für ESP8266 -WLAN Anbindung / Anfänger mizieg 7 202 Gestern 17:45
Letzter Beitrag: N1d45
  ESP8266 OTA und Verwendung von TXD0/RXD0 rev.antun 27 709 22.02.2021 19:43
Letzter Beitrag: hotsystems
  GPS-Synchronisierung mit NodeMCU-ESP8266 Floke4 3 166 22.02.2021 19:33
Letzter Beitrag: rev.antun
  esp8266 zu html gk_1 9 332 19.02.2021 19:41
Letzter Beitrag: Tommy56
  ESP8266 SD CSV Datei Zeilen rückwärtz RobertHQ 7 365 14.02.2021 19:29
Letzter Beitrag: Corvus
  ESP8266 Webserver nach Zeit nicht mehr verfügbar. ESPWolf 21 1.846 02.02.2021 17:54
Letzter Beitrag: Tommy56
  ESP8266 - DLNA, Chromecast, Firestick & YouTube rev.antun 8 702 27.01.2021 21:31
Letzter Beitrag: nbk83
  Fernbedienung mit ESP8266 hardyy 3 440 27.01.2021 08:34
Letzter Beitrag: hardyy
  NodeMCU-ESP8266 Floke4 13 760 25.01.2021 18:17
Letzter Beitrag: hotsystems

Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 1 Gast/Gäste