Hallo Leute, ich komme nicht weiter.
Ich empfange hier auf meinem PC ein Packet welches im Payload ein
String (Char array enthält, ein INT, FLOAT, BOOL).
1 | 54
| 2 | 00 00 38 00 2f 40 40 a0 20 08 00 a0 20 08 00 00
| 3 | 66 59 f9 e5 01 00 00 00 10 02 6c 09 a0 00 d3 00
| 4 | 00 00 00 00 00 00 00 00 a6 58 f9 e5 00 00 00 00
| 5 | 16 00 11 03 d3 00 a8 01 d0 00 00 00 ff ff ff ff
| 6 | ff ff c4 4f 33 0f fe 71 ff ff ff ff ff ff 20 76
| 7 | 7f 18 fe 34 de b1 42 00 dd 31 18 fe 34 04 01 54
| 8 | 48 49 53 20 49 53 20 41 20 43 48 41 52 00 00 00
| 9 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff
| 10 | ff 00 00 00 00 59 42 01 00 00 00 3f f1 01 0e
|
Die Daten werden vom Sender und Empfänger 1:1 aufgebaut:
1 | typedef struct struct_message
| 2 | {
| 3 | uint8_t header[95];
| 4 | char a[32];
| 5 | int b;
| 6 | float c;
| 7 | bool d;
| 8 | } struct_message;
| 9 |
| 10 | struct_message myData;
|
Damit ich den Anfang erwische, habe ich den Header als Dummy im Struct
angelegt (uint8_t header[95];).
Auf der Empgfängerseite kopiere ich mir das mit memcpy in das Struct.
Soweit so gut, die Zeichenkette wird korrekt ausgegeben aber INT,
FLOAT,BOOL
nicht. Die Werte scheinen als little Endian abgelegt.
Wie gehe ich damit um?
1 | memcpy(&myData, data, sizeof(myData));
| 2 |
| 3 | printf("char:%s\n", myData.a);
| 4 | printf("int:%d\n", myData.b);
| 5 | printf("float:%f\n", myData.c);
| 6 | printf("bool:%d\n", myData.d);
|
Auf der Senderseite werden die Daten wie folgt erzeugt:
1 | // Set values to send
| 2 | strcpy(myData.a, "THIS IS A CHAR");
| 3 | myData.b = 65535;
| 4 | myData.c = 54.25;
| 5 | myData.d = true;
|
Auf dem Bild im Anhang ist das Char Array markiert, die Nullen nach den
Werten entsprechen (char a[32]) den 32 byte. Danach steht der INT
Wert (65535) in Hex FF FF, dann Float (54.25) in Hex 00 00 59 42.
Zum schluss Bool (1) in Hex 01. Alles 4 byte lang.
Das sollte passen, aber das alignment wird dir den krummen Start nach 95
Byte verschieben.
Du schreibst dir kleine Funktionen, die die Bytes tauschen. POSIX
definiert dafür die Funktionen htonl, htons, ntohl und ntohs, die
zwischen der Endianess der CPU und Big Endian konvertieren.
Wenn Du bei einem int statt 0xffff empfängerseitig 0xff rausbekommst,
klingt das nicht nach einem Endianness-Problem (dann wäre es
0xffff0000), sondern nach einem Alignment-Problem.
Dein header[95] schreit geradezu danach.
Neben big/little endian gäbs auch noch das Stichwörter alignment, dazu
packed.
Wenn’s aber wirklich an der Endianess liegt, gibts per Google oder
ChatGPT Hilfe, wie man die Werte umwandelt.
Oliver
Vielen Dank, für eure Tips.
Wenn das Alignment nicht stimmen würde, würde das Char Array nicht
rauskommen, oder?
Welle 🧐 S. schrieb:
> Wenn das Alignment nicht stimmen würde, würde das Char Array nicht
> rauskommen, oder?
Doch, dafür gilt normalerweise 1-Byte-Alignment, also im Endeffekt
keines.
Das Problem beginnt beim int mit 4-Byte-Alignment.
Gib doch mal ein sizeof(myData) aus.
Debugger hilft auch…
J. S. schrieb:
> Gib doch mal ein sizeof(myData) aus.
> Debugger hilft auch…
Mach ich ...
1 | -------------------------------------------------------------------------
| 2 |
| 3 | 00 00 38 00 2f 40 40 a0 20 08 00 a0 20 08 00 00
| 4 | cf 1f 18 dd 02 00 00 00 10 02 6c 09 a0 00 d3 00
| 5 | 00 00 00 00 00 00 00 00 0f 1f 18 dd 00 00 00 00
| 6 | 16 00 11 03 d3 00 a7 01 d0 00 00 00 ff ff ff ff
| 7 | ff ff c4 4f 33 0f fe 71 ff ff ff ff ff ff 40 79
| 8 | 7f 18 fe 34 18 b8 5f c2 dd 31 18 fe 34 04 01 54
| 9 | 48 49 53 20 49 53 20 41 20 43 48 41 52 00 00 00
| 10 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff
| 11 | ff 00 00 00 00 59 42 01 00 00 00 1b 60 f5 a6
| 12 | -------------------------------------------------------------------------
| 13 |
| 14 | Packet length:143
| 15 | myData:140
| 16 | char:THIS IS A CHAR
| 17 | int:255
| 18 | float:0.000000
| 19 | bool:0
|
140 passt nicht, alignment problem. Auf 1 Byte alignment stellen für die
Struktur, das ist Compilerabhängig.
J. S. schrieb:
> 140 passt nicht, alignment problem. Auf 1 Byte alignment stellen für die
> Struktur, das ist Compilerabhängig.
Hallo Jojos, wie macht man das?
Ich habe letzens bei meiner Streifzügen das hier gefunden:
__attribute__((packed))
1 | typedef struct struct_message
| 2 | {
| 3 | uint8_t header[93];
| 4 | char a[32];
| 5 | int b;
| 6 | float c;
| 7 | bool d;
| 8 | } __attribute__((aligned(4))) struct_message;
|
Wenn ich das benutze bekomme ich:
1 | Packet length:140
| 2 | Packet length:140
| 3 | myData:140
| 4 | char:THIS IS A CHAR
| 5 | int:255
| 6 | float:0.000000
| 7 | bool:123
|
???
Welle 🧐 S. schrieb:
> Auf der Senderseite werden die Daten wie folgt erzeugt
Ist das in Stein gemeisselt, oder kannst Du aus dem 95-Byte-Header auch
einen mit 96 Bytes machen?
Sich nicht an das Alignment zu halten, sorgt je nach Plattform für
schlechtere Performance (z.B. x86), weil aus einem Speicherzugriff zwei
werden, oder knallt sogar (z.B. m68k).
Hmmm schrieb:
> Welle 🧐 S. schrieb:
>> Auf der Senderseite werden die Daten wie folgt erzeugt
>
> Ist das in Stein gemeisselt
Eigentlich müsste die Frage: woher du wissen, junger Padavan?
Oliver
J. S. schrieb:
> 140 passt nicht, alignment problem. Auf 1 Byte alignment stellen für die
> Struktur, das ist Compilerabhängig.
Ok, habe ich gemacht ...
1 | typedef struct struct_message
| 2 | {
| 3 | uint8_t header[93]; // 2 Byte
| 4 | char a[32]; // 2 Byte
| 5 | int b; // 4 Byte
| 6 | float c; // 4 byte
| 7 | bool d; // 4 Byte
| 8 | }__attribute__((packed, aligned(1))) struct_message; struct_message myData;
|
https://stackoverflow.com/questions/11770451/what-is-the-meaning-of-attribute-packed-aligned4
https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html
Aber kein Erfolg:
1 | Packet length:143
| 2 | Struct size of myData:140
| 3 | Struct size of myTest:8
| 4 | char:THIS IS A CHAR
| 5 | int:39
| 6 | float:0.000000
| 7 | bool:0
|
MyTest war ein Test:
1 | typedef struct teststruct
| 2 | {
| 3 | char Data1;
| 4 | int Data2;
| 5 | unsigned short Data3;
| 6 | char Data4;
| 7 |
| 8 | }__attribute__((packed, aligned(1))) teststruct; teststruct myTest;
|
Hmm ...
ENTWARNUNG! Ich habe nochmal die Packete (Wshark) durchgezählt ...
Siehe da:
1 | typedef struct struct_message
| 2 | {
| 3 | uint8_t header[56]; // 2 Byte
| 4 | uint8_t action[24]; // 2 Byte
| 5 | uint8_t vendor[1]; // 2 Byte
| 6 | uint8_t oui[3]; // 2 Byte
| 7 | uint8_t noidea[11]; // 2 Byte
| 8 | char a[32]; // 2 Byte
| 9 | int b; // 4 Byte
| 10 | float c; // 4 byte
| 11 | bool d; // 4 Byte
| 12 | }__attribute__((packed, aligned(1))) struct_message; struct_message myData;
|
1 | Packet length:143
| 2 | Struct size of myData:136
| 3 | char:THIS IS A CHAR
| 4 | int:9999
| 5 | float:54.250000
| 6 | bool:1
|
Bingo!
Die headersize stimmt noch nicht. Der Header ist doch im Espressif IDK
definiert.
Das mit der String Ausgabe ist keine sichere Methode den Anfang zu
finden, da sind zwei nicht druckbare Zeichen vor die du auch treffen
kannst.
Also printf("%x/n", myData[0]);
Und wieso ständig andere Strukturen? Da blickt doch keiner mehr durch.
Moin,
Welle 🧐 S. schrieb:
> uint8_t header[56]; // 2 Byte
> uint8_t action[24]; // 2 Byte
> uint8_t vendor[1]; // 2 Byte
> uint8_t oui[3]; // 2 Byte
> uint8_t noidea[11]; // 2 Byte
> char a[32]; // 2 Byte
Endlich mal klare Kommentare im src ;-)
scnr,
WK
Na Glückwunsch, trotzdem ist es besser den richtigen Header zu
verwenden. Da stecken auch interessante Sachen wie RSSI Werte drin.
Ich habe jetzt aus faulheit die Radiotapdaten rausgepopelt.
Spannend ist, am Ende das FCS Packet.
Das muss ich mir noch erarbeiten.
1 | typedef struct struct_message
| 2 | {
| 3 | uint8_t radio_tap_header[95];
| 4 | int b;
| 5 | float c;
| 6 | bool d;
| 7 | uint8_t pad_for_bool[3];
| 8 | float e;
| 9 | int fcs;
| 10 | }__attribute__((packed, aligned(1))) struct_message;
| 11 | struct_message myData;
| 12 |
| 13 |
| 14 | void print_packet(uint8_t *data, int len)
| 15 | {
| 16 | memcpy(&myData, data, len);
| 17 |
| 18 | printf("packet laenge: %d\n",len);
| 19 | printf("sizeof(myData): %ld\n",sizeof(myData));
| 20 | printf("antenna signal:%d\n", myData.radio_tap_header[30]);
| 21 | printf("int:%d\n", myData.b);
| 22 | printf("float:%.3f\n", myData.c);
| 23 | printf("bool:%d\n", myData.d);
| 24 | printf("float:%.3f\n", myData.e);
| 25 |
| 26 | printf("\n");
| 27 | }
|
Welle 🧐 S. schrieb:
> 1 | > typedef struct struct_message
| 2 | > {
| 3 | > uint8_t header[56]; // 2 Byte
| 4 | > uint8_t action[24]; // 2 Byte
| 5 | > uint8_t vendor[1]; // 2 Byte
| 6 | > uint8_t oui[3]; // 2 Byte
| 7 | > uint8_t noidea[11]; // 2 Byte
| 8 | > char a[32]; // 2 Byte
| 9 | > int b; // 4 Byte
| 10 | > float c; // 4 byte
| 11 | > bool d; // 4 Byte
| 12 | > }__attribute__((packed, aligned(1))) struct_message; struct_message
| 13 | > myData;
| 14 | >
|
Falls das hier mal jemand findet, BOOL ist nur EIN Byte und muss
mit einem Pad[3] aufgefüllt werden ... es hatt nur funktioniert weil
es am Ende stand.
Welle 🧐 S. schrieb:
> Falls das hier mal jemand findet, BOOL ist nur EIN Byte und muss
> mit einem Pad[3] aufgefüllt werden ... es hatt nur funktioniert weil
> es am Ende stand.
Aber das weiß man doch. Das ist doch schon seit Jahrzehnten so.
Spätestens mit der breiten Einführung dem M68000 Mitte der 80er wurde
das so gemacht.
"68000 und 68010 können nur byteweise auf ungerade Adressen zugreifen.
Diese Exception wird ausgelöst, wenn man dennoch einen Wort- oder
Langwort-Zugriff versucht (auch Programmzähler oder Stack-Pointer dürfen
keine ungeraden Adressen enthalten)."
https://freemint.github.io/tos.hyp/de/the_system_vectors.html
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|